package com.btpn.custody.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.btpn.custody.bean.ParameterBeans;
import com.btpn.custody.common.Constant;
import com.btpn.custody.dao.IArea;
import com.btpn.custody.dao.IBranch;
import com.btpn.custody.dao.IMasterData;
import com.btpn.custody.entity.Account;
import com.btpn.custody.entity.Area;
import com.btpn.custody.entity.Branch;
import com.btpn.custody.entity.MasterData;
import com.btpn.custody.service.IBranchService;
import com.btpn.custody.web.m002.model.BranchModel;
import com.btpn.custody.web.m002.model.Param;
import com.btpn.infra.utils.MyDateUtils;

@Service("branchService")
@Transactional
public class BranchServiceImpl implements IBranchService {
	
	@Autowired
	private IArea areaDaoHibernate;

	@Autowired @Qualifier("branchDaoHibernate")
	private IBranch branchDao;
	
	@Autowired
	private IMasterData masterDataDaoHibernate;
	
	@Autowired
	private ParameterBeans parameterBeans;
	
	// unused
	@Override
	public void createBranch(Branch branch, Long areaId) {
		// get area by areaId
		Area area = areaDaoHibernate.get(areaId);
		
		// set area to branch
		branch.setArea(area);
		
		branchDao.create(branch);
	}

//	@Override
//	public List<Branch> findAllBranch() {
//		return branchDao.findAll();
//	}

//	@Override
//	public Branch getBranch(Long id) {
//		return branchDao.get(id);
//	}

	// unused
	@Override
	public void updateBranch(Long branchId, String code, String name, Long newAreaId) throws Exception {		
		// get area by areaId
		Area area = areaDaoHibernate.get(newAreaId);
		
		// get edited branch
		Branch branch = branchDao.get(branchId);
		branch.setCode(code);
		branch.setName(name);
		branch.setArea(area);
		
		branchDao.update(branch);
	}
	
	@Override
	public BranchModel search(Long areaId, String status, String keyword, String branchCode, String accCode, String cstCode, Date from, Date to) {

		return generateBMbyStatus(masterDataDaoHibernate.search(areaId, status, keyword, branchCode, accCode, cstCode, from, to), status, from, to);
	}

	/*
	 * PURPOSE : generate BranchModel.MasterModel based on status
	 * - Receiving 	: NPY 		-> Master2Model
	 * - Completing	: RECEIVED	-> Master3Model
	 * - Checklist	: PROGRESS	-> MasterModel
	 */
	private BranchModel generateBMbyStatus(List<MasterData> mds, String status, Date from, Date to) {
		BranchModel bm = new BranchModel();		
		
		if (status.equals(Constant.STATUS__MD_NPY)) {					// from Receiving
			for (MasterData md : mds) {
				bm.setBranchName(md.getBranch().getName());

				// for each account
				for (Account a : md.getAccounts()) {
					if ((from==null) && (to!=null)) {						// from last until to	
						if (a.getACCOUNT_OPEN().getTime() < DateUtils.addDays(to, 1).getTime()) {
							BranchModel.Master2Model mm = bm.new Master2Model();
							mm.setSid(md.getSid());
							mm.setCstName(md.getCIF().getCUST_FULL_NAME());
							
							mm.setAccount(a.getACCOUNT());
							mm.setAccType(parameterBeans.getAccountTypeValue(a.getACCOUNT_TYPE()));
//							mm.setRekType(a.getREKENING_TYPE());
							mm.setAccOpen(MyDateUtils.dateToStr(Constant.FORMAT_SQLSERVER, a.getACCOUNT_OPEN()));
							
							bm.getMaster2Models().add(mm);
						}
					} else if ((from!=null) && (to==null)) {				// from from until now
						if (a.getACCOUNT_OPEN().getTime() > DateUtils.addSeconds(from, -1).getTime()) {
							BranchModel.Master2Model mm = bm.new Master2Model();
							mm.setSid(md.getSid());
							mm.setCstName(md.getCIF().getCUST_FULL_NAME());
							
							mm.setAccount(a.getACCOUNT());
							mm.setAccType(parameterBeans.getAccountTypeValue(a.getACCOUNT_TYPE()));
//							mm.setRekType(a.getREKENING_TYPE());
							mm.setAccOpen(MyDateUtils.dateToStr(Constant.FORMAT_SQLSERVER, a.getACCOUNT_OPEN()));
							
							bm.getMaster2Models().add(mm);
						}
					} else if ((from != null) && (to != null)) {
						if ((from.getTime() <= a.getACCOUNT_OPEN().getTime()) & (a.getACCOUNT_OPEN().getTime() <= DateUtils.addSeconds(DateUtils.addDays(to, 1), -1).getTime())) {
							BranchModel.Master2Model mm = bm.new Master2Model();
							mm.setSid(md.getSid());
							mm.setCstName(md.getCIF().getCUST_FULL_NAME());
							
							mm.setAccount(a.getACCOUNT());
							mm.setAccType(parameterBeans.getAccountTypeValue(a.getACCOUNT_TYPE()));
//							mm.setRekType(a.getREKENING_TYPE());
							mm.setAccOpen(MyDateUtils.dateToStr(Constant.FORMAT_SQLSERVER, a.getACCOUNT_OPEN()));
							
							bm.getMaster2Models().add(mm);
						}
			        }					
				}
			}		

		} else if (status.equals(Constant.STATUS__MD_RECEIVED)) {		// from Completing
			for (MasterData md : mds) {
				bm.setBranchName(md.getBranch().getName());

				// for each account
				for (Account a : md.getAccounts()) {
					if ((from==null) && (to!=null)) {						// from last until to	
						if (a.getACCOUNT_OPEN().getTime() < DateUtils.addDays(to, 1).getTime()) {
							BranchModel.Master3Model mm = bm.new Master3Model();
							mm.setSid(md.getSid());
							mm.setCstName(md.getCIF().getCUST_FULL_NAME());
							mm.setCurrStatus(md.getSTATUS_MD());
							
							mm.setAccount(a.getACCOUNT());
							mm.setAccType(parameterBeans.getAccountTypeValue(a.getACCOUNT_TYPE()));
							mm.setAccOpen(MyDateUtils.dateToStr(Constant.FORMAT_SQLSERVER, a.getACCOUNT_OPEN()));							
							
							bm.getMaster3Models().add(mm);
						}
					} else if ((from!=null) && (to==null)) {				// from from until now
						if (a.getACCOUNT_OPEN().getTime() > DateUtils.addSeconds(from, -1).getTime()) {
							BranchModel.Master3Model mm = bm.new Master3Model();
							mm.setSid(md.getSid());
							mm.setCstName(md.getCIF().getCUST_FULL_NAME());
							mm.setCurrStatus(md.getSTATUS_MD());
							
							mm.setAccount(a.getACCOUNT());
							mm.setAccType(parameterBeans.getAccountTypeValue(a.getACCOUNT_TYPE()));
							mm.setAccOpen(MyDateUtils.dateToStr(Constant.FORMAT_SQLSERVER, a.getACCOUNT_OPEN()));							
							
							bm.getMaster3Models().add(mm);
						}
					} else if ((from != null) && (to != null)) {
						if ((from.getTime() <= a.getACCOUNT_OPEN().getTime()) & (a.getACCOUNT_OPEN().getTime() <= DateUtils.addSeconds(DateUtils.addDays(to, 1), -1).getTime())) {
							BranchModel.Master3Model mm = bm.new Master3Model();
							mm.setSid(md.getSid());
							mm.setCstName(md.getCIF().getCUST_FULL_NAME());
							mm.setCurrStatus(md.getSTATUS_MD());
							
							mm.setAccount(a.getACCOUNT());
							mm.setAccType(parameterBeans.getAccountTypeValue(a.getACCOUNT_TYPE()));
							mm.setAccOpen(MyDateUtils.dateToStr(Constant.FORMAT_SQLSERVER, a.getACCOUNT_OPEN()));							
							
							bm.getMaster3Models().add(mm);
						}
			        }					
				}
			}		

		} else if (status.equals(Constant.STATUS__MD_COMPLETED)) {		// from Checklist
			for (MasterData md : mds) {
				bm.setBranchName(md.getBranch().getName());
				
				// for each account
				for (Account a : md.getAccounts()) {
					if ((from==null) && (to!=null)) {						// from last until to	
						if (a.getACCOUNT_OPEN().getTime() < DateUtils.addDays(to, 1).getTime()) {
							BranchModel.MasterModel mm = bm.new MasterModel();
							
							// the same for each MasterModel
							mm.setSid(md.getSid());										// i set masterId, not cifId
							mm.setNAMA_NASABAH(md.getCIF().getCUST_FULL_NAME());
							mm.setTIPE_NASABAH(parameterBeans.getCustomerTypeValue(md.getCIF().getCUSTOMER_TYPE()));
							mm.setSTATUS(md.getSTATUS_MD());
							
							// the difference for each MasterModel
							mm.setJENIS_REKENING(parameterBeans.getAccountTypeValue(a.getACCOUNT_TYPE()));		
							mm.setNO_REKENING(a.getACCOUNT());
							mm.setACC_OPEN(MyDateUtils.dateToStr(Constant.FORMAT_SQLSERVER, a.getACCOUNT_OPEN()));
							
							bm.getMasterModels().add(mm);
						}
					} else if ((from!=null) && (to==null)) {				// from from until now
						if (a.getACCOUNT_OPEN().getTime() > DateUtils.addSeconds(from, -1).getTime()) {
							BranchModel.MasterModel mm = bm.new MasterModel();
							
							// the same for each MasterModel
							mm.setSid(md.getSid());										// i set masterId, not cifId
							mm.setNAMA_NASABAH(md.getCIF().getCUST_FULL_NAME());
							mm.setTIPE_NASABAH(parameterBeans.getCustomerTypeValue(md.getCIF().getCUSTOMER_TYPE()));
							mm.setSTATUS(md.getSTATUS_MD());
							
							// the difference for each MasterModel
							mm.setJENIS_REKENING(parameterBeans.getAccountTypeValue(a.getACCOUNT_TYPE()));		
							mm.setNO_REKENING(a.getACCOUNT());
							mm.setACC_OPEN(MyDateUtils.dateToStr(Constant.FORMAT_SQLSERVER, a.getACCOUNT_OPEN()));
							
							bm.getMasterModels().add(mm);
						}
					} else if ((from != null) && (to != null)) {
						if ((from.getTime() <= a.getACCOUNT_OPEN().getTime()) & (a.getACCOUNT_OPEN().getTime() <= DateUtils.addSeconds(DateUtils.addDays(to, 1), -1).getTime())) {
							BranchModel.MasterModel mm = bm.new MasterModel();
							
							// the same for each MasterModel
							mm.setSid(md.getSid());										// i set masterId, not cifId
							mm.setNAMA_NASABAH(md.getCIF().getCUST_FULL_NAME());
							mm.setTIPE_NASABAH(parameterBeans.getCustomerTypeValue(md.getCIF().getCUSTOMER_TYPE()));
							mm.setSTATUS(md.getSTATUS_MD());
							
							// the difference for each MasterModel
							mm.setJENIS_REKENING(parameterBeans.getAccountTypeValue(a.getACCOUNT_TYPE()));		
							mm.setNO_REKENING(a.getACCOUNT());
							mm.setACC_OPEN(MyDateUtils.dateToStr(Constant.FORMAT_SQLSERVER, a.getACCOUNT_OPEN()));
							
							bm.getMasterModels().add(mm);
						}
			        }					
				}
			}
		} else if (status.equals(Constant.STATUS__MD_WAIT4APP)) {		// from Approval (persis Checklist)
			for (MasterData md : mds) {
				bm.setBranchName(md.getBranch().getName());
				
				// for each account
				for (Account a : md.getAccounts()) {	
					if ((from==null) && (to!=null)) {						// from last until to	
						if (a.getACCOUNT_OPEN().getTime() < DateUtils.addDays(to, 1).getTime()) {
							BranchModel.MasterModel mm = bm.new MasterModel();
							
							// the same for each MasterModel
							mm.setSid(md.getSid());										// i set masterId, not cifId
							mm.setNAMA_NASABAH(md.getCIF().getCUST_FULL_NAME());
							mm.setTIPE_NASABAH(parameterBeans.getCustomerTypeValue(md.getCIF().getCUSTOMER_TYPE()));
							mm.setSTATUS(md.getSTATUS_MD());
							
							// the difference for each MasterModel
							mm.setJENIS_REKENING(parameterBeans.getAccountTypeValue(a.getACCOUNT_TYPE()));		
							mm.setNO_REKENING(a.getACCOUNT());
							mm.setACC_OPEN(MyDateUtils.dateToStr(Constant.FORMAT_SQLSERVER, a.getACCOUNT_OPEN()));
							
							bm.getMasterModels().add(mm);
						}
					} else if ((from!=null) && (to==null)) {				// from from until now
						if (a.getACCOUNT_OPEN().getTime() > DateUtils.addSeconds(from, -1).getTime()) {
							BranchModel.MasterModel mm = bm.new MasterModel();
							
							// the same for each MasterModel
							mm.setSid(md.getSid());										// i set masterId, not cifId
							mm.setNAMA_NASABAH(md.getCIF().getCUST_FULL_NAME());
							mm.setTIPE_NASABAH(parameterBeans.getCustomerTypeValue(md.getCIF().getCUSTOMER_TYPE()));
							mm.setSTATUS(md.getSTATUS_MD());
							
							// the difference for each MasterModel
							mm.setJENIS_REKENING(parameterBeans.getAccountTypeValue(a.getACCOUNT_TYPE()));		
							mm.setNO_REKENING(a.getACCOUNT());
							mm.setACC_OPEN(MyDateUtils.dateToStr(Constant.FORMAT_SQLSERVER, a.getACCOUNT_OPEN()));
							
							bm.getMasterModels().add(mm);
						}
					} else if ((from != null) && (to != null)) {
						if ((from.getTime() <= a.getACCOUNT_OPEN().getTime()) & (a.getACCOUNT_OPEN().getTime() <= DateUtils.addSeconds(DateUtils.addDays(to, 1), -1).getTime())) {
							BranchModel.MasterModel mm = bm.new MasterModel();
							
							// the same for each MasterModel
							mm.setSid(md.getSid());										// i set masterId, not cifId
							mm.setNAMA_NASABAH(md.getCIF().getCUST_FULL_NAME());
							mm.setTIPE_NASABAH(parameterBeans.getCustomerTypeValue(md.getCIF().getCUSTOMER_TYPE()));
							mm.setSTATUS(md.getSTATUS_MD());
							
							// the difference for each MasterModel
							mm.setJENIS_REKENING(parameterBeans.getAccountTypeValue(a.getACCOUNT_TYPE()));		
							mm.setNO_REKENING(a.getACCOUNT());
							mm.setACC_OPEN(MyDateUtils.dateToStr(Constant.FORMAT_SQLSERVER, a.getACCOUNT_OPEN()));
							
							bm.getMasterModels().add(mm);
						}
			        }					
				}
			}
		}
		
		return bm;
	}
	
//	@Override
//	public BranchModel getBMbyBranchId_Status(Long branchId, String status) {
//		
//		// Rule of Completing view are STATUS is in RECEIVED and still TBO
//		if (status==Constant.STATUS__MD_RECEIVED) {
//			return generateBMbyStatus(masterDataDaoHibernate.findByBranchIdWith2Status(branchId, Constant.STATUS__MD_RECEIVED, Constant.STATUS__MD_TBO), status);
//		}
//		
//		// for Receiving, Checklist & Approval
//		return generateBMbyStatus(masterDataDaoHibernate.findByBranchIdWithStatus(branchId, status), status);
//	}

	@Override
	public List<Param> findBranchMap(Long areaId, String status) {

		List<Param> results = new ArrayList<Param>();
		
		// sederhanakan lewat namedQuery
		for (Branch b : branchDao.findByAreaId(areaId)) {
//			int count=0;
//			for (MasterData md : b.getMasterDatas()) { 
//				if (md.getSTATUS_MD().equals(status)) {
//					count++;
//				}
//			}
			results.add(new Param(b.getId().toString(), b.getName()));
		}
		return results;
	}
}
